/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.basics.editor;

import java.io.File;
import java.rmi.server.UID;
import java.util.List;

import com.genia.toolbox.basics.editor.gui.AbstractGUI;
import com.genia.toolbox.basics.editor.model.bean.InitialSettings;
import com.genia.toolbox.basics.editor.model.document.Document;
import com.genia.toolbox.basics.editor.model.document.Element;
import com.genia.toolbox.basics.i18n.I18nMessage;
import com.genia.toolbox.web.portlet.description.ContainerPortletDescription.LayoutDirection;

/**
 * The basic controller.
 * 
 * @param <A>
 *          The generic application.
 * @param <G>
 *          The generic gui.
 * @param <D>
 *          The generic document.
 * @param <E>
 *          The generic element.
 * @param <I>
 *          The generic initial settings.
 */
public abstract class AbstractController<A extends AbstractApplication<?, D, E, I>, G extends AbstractGUI<?, ?, ?, D, E, I>, D extends Document<E>, E extends Element<?>, I extends InitialSettings>
{

  /**
   * The editor application.
   */
  private A editorApplication;

  /**
   * The editor GUI.
   */
  private G editorGUI;



  /**
   * Constructor.
   * 
   * @param editorApplication
   *          The editor application.
   * @param editorGUI
   *          GUI. The editorGUI.
   */
  public AbstractController(A editorApplication, G editorGUI)
  {
    super();
    this.editorApplication = editorApplication;
    this.editorGUI = editorGUI;
  }



  /**
   * Notify a document opening from a backup file.
   */
  public void notifyCreateOpenDocument()
  {
    this.getApplication().openDocument();
  }



  /**
   * Get the application.
   * 
   * @return the application.
   */
  public A getApplication()
  {
    return this.editorApplication;
  }



  /**
   * Get the GUI.
   * 
   * @return the GUI.
   */
  public G getGUI()
  {
    return this.editorGUI;
  }



  /**
   * Notify a translation attempt.
   * 
   * @param key
   *          the key.
   * @return the translation.
   */
  public String notifyTranslation(String key)
  {
    return this.getApplication().getTranslation(key);
  }



  /**
   * Notify a translation attempt.
   * 
   * @param key
   *          the key.
   * @param parameters
   *          the parameters.
   * @return the translation.
   */
  public String notifyTranslation(String key, String[] parameters)
  {
    return this.getApplication().getTranslation(key, parameters);
  }



  /**
   * Notify a translation attempt.
   * 
   * @param message
   *          the message.
   * @return the translation.
   */
  public String notifyTranslation(I18nMessage message)
  {
    return this.getApplication().getTranslation(message);
  }



  /**
   * Notify that the getApplication() could not be initialised.
   * 
   * @param title
   *          The title.
   * @param message
   *          The message.
   */
  public void notifyInitialisationError(String title, String message)
  {
    this.getGUI().warn(title, message);
    this.getApplication().close();
  }



  /**
   * Notify an getApplication() closure.
   */
  public void notifyCloseApplication()
  {
    this.getApplication().close();
  }



  /**
   * Notify an getApplication() closure.
   */
  public void notifyRefreshActionRights()
  {
    this.getGUI().refresh();
  }



  /**
   * Notify that a question is asked to the user.
   * 
   * @param title
   *          the title.
   * @param message
   *          the message.
   * @return the answer.
   */
  public boolean notifyAskUser(String title, String message)
  {
    return this.getGUI().ask(title, message);
  }



  /**
   * Notify that a message is told to the user.
   * 
   * @param title
   *          the title.
   * @param message
   *          the message.
   */
  public void notifyTellUser(String title, String message)
  {
    this.getGUI().tell(title, message);
  }



  /**
   * Notify a backup file selection.
   * 
   * @return The file.
   */
  public File notifySelectABackupFile()
  {
    return this.getGUI().saveXMLFile();
  }



  /**
   * Notify a file opening.
   * 
   * @return The file.
   */
  public File notifyOpenAFile()
  {
    return this.getGUI().openXMLFile();
  }



  /**
   * Notify the first display of a document.
   * 
   * @param document
   *          the first display of a document.
   */
  public void notifyFirstDisplayDocument(D document)
  {
    this.getGUI().firstDisplayDocument(document);
    this.notifyRefreshActionRights();
  }



  /**
   * Notify a document creation.
   * 
   * @param settings
   *          The document initial settings.
   */
  public void notifyCreateNewDocument(I settings)
  {
    this.getApplication().createNewDocument(settings);
  }



  /**
   * Notify the display of a document.
   * 
   * @param document
   *          the display of a document.
   */
  public void notifyDisplayDocument(D document)
  {
    this.getGUI().displayDocument(document);
    this.notifyRefreshActionRights();
  }



  /**
   * Notify a document closure.
   * 
   * @param document
   *          The document.
   */
  public void notifyCloseDocument(D document)
  {
    this.getApplication().closeDocument(document);
  }



  /**
   * Notify that a document has to be hidden.
   * 
   * @param documentUniqueID
   *          the document unique ID.
   */
  public void notifyHideDocument(UID documentUniqueID)
  {
    this.getGUI().hideDocument(documentUniqueID);
    this.notifyRefreshActionRights();
  }



  /**
   * Return the displayed document.
   * 
   * @param documentUniqueID
   *          the document unique ID.
   * @return the displayed document.
   */
  public D notifyRefreshDocument(UID documentUniqueID)
  {
    return this.getGUI().getDocument(documentUniqueID);
  }



  /**
   * Notify a document saving action.
   * 
   * @param document
   *          The document.
   */
  public void notifySaveDocument(D document)
  {
    this.getApplication().saveDocument(document);
  }



  /**
   * Notify all documents saving attempt.
   */
  public void notifySaveAllDocuments()
  {
    this.getApplication().saveAllDocuments();
  }



  /**
   * Return the list of the displayed documents.
   * 
   * @return The list of displayed documents.
   */
  public List<UID> notifyListDisplayedDocuments()
  {
    return this.getGUI().getAllDocumentsUniqueID();
  }



  /**
   * Notify all documents closing attempt.
   */
  public void notifyCloseAllDocuments()
  {
    this.getApplication().closeAllDocuments();
  }



  /**
   * Notify a sub element creation.
   * 
   * @param settings
   *          the sub element initial settings.
   * @param documentUniqueID
   *          the document unique ID.
   * @param parentUniqueID
   *          the parent element unique ID.
   * @param direction
   *          the layout direction.
   */
  public void notifyCreateSubElement(I settings, UID documentUniqueID, UID parentUniqueID, LayoutDirection direction)
  {
    this.getApplication().createNewSubElement(settings, documentUniqueID, parentUniqueID, direction);
  }



  /**
   * Notify the display of an element.
   * 
   * @param element
   *          an element.
   */
  public void notifyDisplaySubElement(E element)
  {
    this.getGUI().displaySubElement(element);
  }



  /**
   * Return the element displayed in the settings panel.
   * 
   * @return the element displayed in the settings panel.
   */
  public E notifyRefreshElementFromSettings()
  {
    return this.getGUI().getUpdatedElementFromSettings();
  }



  /**
   * Notify the cut of an element.
   * 
   * @param element
   *          an element.
   */
  public void notifyCutElement(E element)
  {
    if (element != null) {
      this.getApplication().setCutElement(element);
      this.getGUI().deleteSubElement(element);
    }
  }



  /**
   * Notify the paste of an element.
   * 
   * @param element
   *          an element.
   */
  public void notifyPasteElement(E element)
  {
    if (element != null) {
      this.getApplication().pasteElement(this.getApplication().getCutElement(), element);
      this.getApplication().setCutElement(null);
    }
  }



  /**
   * Notify whether there is a cut element.
   * 
   * @return whether there is a cut element.
   */
  public boolean notifyHasCutElement()
  {
    boolean hasCutElement = false;
    if (this.getApplication().getCutElement() != null) {
      hasCutElement = true;
    }
    return hasCutElement;
  }

}
